package com.linln.admin.lzgd.controller;

import com.linln.admin.lzgd.validator.BaseInfoValid;
import com.linln.common.enums.StatusEnum;
import com.linln.common.exception.ResultException;
import com.linln.common.jpahelper.BaseCriteria;
import com.linln.common.jpahelper.Criteria;
import com.linln.common.jpahelper.Restrictions;
import com.linln.common.utils.*;
import com.linln.common.vo.ResultVo;
import com.linln.component.excel.ExcelReader;
import com.linln.component.fileUpload.FileUpload;
import com.linln.component.fileUpload.enums.UploadResultEnum;
import com.linln.component.jwt.annotation.IgnorePermissions;
import com.linln.modules.api.exceptions.ProjectMatchException;
import com.linln.modules.gdp.domain.RegionGdp;
import com.linln.modules.gdp.service.impl.RegionGdpServiceImpl;
import com.linln.modules.lzgd.domain.BaseInfo;
import com.linln.modules.lzgd.service.BaseInfoService;
import com.linln.modules.system.domain.Upload;
import com.linln.modules.system.service.UploadService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 小懒虫
 * @date 2023/12/03
 */
@Controller
@RequestMapping("/lzgd/baseInfo")
public class BaseInfoController {

    @Autowired
    private BaseInfoService baseInfoService;
    @Autowired
    private UploadService uploadService;

    private static int FIELD_ROW = 0;
    /**
     * 列表页面
     */
    @GetMapping("/index")
    @RequiresPermissions("lzgd:baseInfo:index")
    public String index(Model model, BaseInfo baseInfo) {

        // 创建匹配器，进行动态查询匹配
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("sqs", match -> match.contains());

        // 获取数据列表
        Example<BaseInfo> example = Example.of(baseInfo, matcher);
        Page<BaseInfo> list = baseInfoService.getPageList(example);

        // 封装数据
        model.addAttribute("list", list.getContent());
        model.addAttribute("page", list);
        return "/lzgd/baseInfo/index";
    }

    /**
     * 跳转到添加页面
     */
    @GetMapping("/add")
    @RequiresPermissions("lzgd:baseInfo:add")
    public String toAdd() {
        return "/lzgd/baseInfo/add";
    }

    /**
     * 跳转到编辑页面
     */
    @GetMapping("/edit/{id}")
    @RequiresPermissions("lzgd:baseInfo:edit")
    public String toEdit(@PathVariable("id") BaseInfo baseInfo, Model model) {
        model.addAttribute("baseInfo", baseInfo);
        return "/lzgd/baseInfo/add";
    }

    /**
     * 保存添加/修改的数据
     * @param valid 验证对象
     */
    @PostMapping("/save")
    @RequiresPermissions({"lzgd:baseInfo:add", "lzgd:baseInfo:edit"})
    @ResponseBody
    public ResultVo save(@Validated BaseInfoValid valid, BaseInfo baseInfo) {
        // 复制保留无需修改的数据
        if (baseInfo.getId() != null) {
            BaseInfo beBaseInfo = baseInfoService.getById(baseInfo.getId());
            EntityBeanUtil.copyProperties(beBaseInfo, baseInfo);
        }

        // 保存数据
        baseInfoService.save(baseInfo);
        return ResultVoUtil.SAVE_SUCCESS;
    }

    /**
     * 跳转到详细页面
     */
    @GetMapping("/detail/{id}")
    @RequiresPermissions("lzgd:baseInfo:detail")
    public String toDetail(@PathVariable("id") BaseInfo baseInfo, Model model) {
        model.addAttribute("baseInfo",baseInfo);
        return "/lzgd/baseInfo/detail";
    }

    /**
     * 设置一条或者多条数据的状态
     */
    @RequestMapping("/status/{param}")
    @RequiresPermissions("lzgd:baseInfo:status")
    @ResponseBody
    public ResultVo status(
            @PathVariable("param") String param,
            @RequestParam(value = "ids", required = false) List<Long> ids) {
        // 更新状态
        StatusEnum statusEnum = StatusUtil.getStatusEnum(param);
        if (baseInfoService.updateStatus(statusEnum, ids)) {
            return ResultVoUtil.success(statusEnum.getMessage() + "成功");
        } else {
            return ResultVoUtil.error(statusEnum.getMessage() + "失败，请重新操作");
        }
    }

    @GetMapping({"/import"})
    @RequiresPermissions({"lzgd:baseInfo:import"})
    @IgnorePermissions
    public String match() {
        return "/lzgd/baseInfo/import";
    }


    /**
     * 统计新增农村乱占更多数据
     */
    @GetMapping("/statNewLZCount")
    @ResponseBody
    public  ResultVo   statNewLZCount(
            @RequestParam(required = false) String qrxzYear,
            @RequestParam(required = false) String sfzgdw) {
        Criteria<BaseInfo> criteria=new BaseCriteria<>();
        if(qrxzYear!=null){
            criteria.addAnd(Restrictions.eq("qrxzYear",qrxzYear));
        }
        if(sfzgdw!=null){
            criteria.addAnd(Restrictions.eq("sfzgdw",sfzgdw));
        }
        List<BaseInfo> documents = baseInfoService.findAll(criteria);
        int count=documents.size();
        return ResultVoUtil.success(count);
    }


    /**
     * 文件上传
     */
    @PostMapping("/upload")
    @ResponseBody
    public ResultVo uploadGdpFile(@RequestParam("lzgdFile") MultipartFile multipartFile) {

        // 创建Upload实体对象
        Upload upload = FileUpload.getFile(multipartFile, "/lzgdFile");
        try {
            String[] types = {
                    "application/vnd.ms-excel",
            };
            if(!FileUpload.isContentType(multipartFile, types)){
                throw new ResultException(UploadResultEnum.NO_FILE_TYPE);
            }

            // 判断文件是否存在
            Upload uploadSha1 = uploadService.getBySha1(FileUpload.getFileSha1(multipartFile));
            if (uploadSha1 != null) {
                return ResultVoUtil.success(uploadSha1);
            }

            FileUpload.transferTo(multipartFile, upload);
            // 将文件信息保存到数据库中
            uploadService.save(upload);
            return ResultVoUtil.success(upload);
        } catch (IOException | NoSuchAlgorithmException e) {
            return ResultVoUtil.error("上传GDP文件失败");
        }
    }

    @PostMapping({"/excImport"})
    @ResponseBody
    public ResultVo excImport(@RequestParam("upFileId") String upFileId) {
        Upload upload = this.uploadService.getById(Long.valueOf(upFileId));
        String basePath = FileUpload.getUploadPath();
        String absUrl = basePath.substring(0, basePath.length() - 8) + upload.getPath();
        File file = new File(absUrl);
        FileInputStream fis = null;

        try {
            fis = new FileInputStream(file);
            ExcelReader reader = new ExcelReader();
            boolean isOffice2003 = ExcelReader.isExcel2003(file.getName());
            List<List<String>> rows = reader.read(fis, isOffice2003);
            Map<String, Integer> fieldMap = this.getFieldMap(rows, FIELD_ROW);
            List<BaseInfo> oldLzgdBaseInfos=this.baseInfoService.findAll(null);
            List<BaseInfo> lzgdBaseInfos = this.parseBaseInfos( rows, fieldMap);
            StringBuffer validMsg = this.baseInfoService.validLzgdBaseInfo(lzgdBaseInfos);


            if (validMsg.length() > 0) {
                return ResultVoUtil.error(validMsg.toString());
            }

            //处理时间

            List<BaseInfo> newLzgdBaseInfos = new ArrayList();
           for(int i=0;i<lzgdBaseInfos.size();i++){
               BaseInfo newLzgdBaseInfo=lzgdBaseInfos.get(i);

               String jcbh=newLzgdBaseInfo.getJcbh();
               BaseInfo oldLzgdBaseInfo=this.baseInfoService.getByJcbh(jcbh);
               if(oldLzgdBaseInfo!=null){
                   boolean isEqual=oldLzgdBaseInfo.equals(newLzgdBaseInfo);
                   if(!isEqual){
                       newLzgdBaseInfo.setId(oldLzgdBaseInfo.getId());
                       newLzgdBaseInfo.setFlag("1");
                       newLzgdBaseInfos.add(newLzgdBaseInfo);
                   }
               }else {
                   newLzgdBaseInfo.setFlag("1");
//                   String currentDate=DateUtil.getNow();
//                   newLzgdBaseInfo.setQrxzMonth(currentDate);
                   newLzgdBaseInfos.add(newLzgdBaseInfo);
               }
           }

            StringBuffer _validMsg = this.baseInfoService.validLzgdBaseInfo(newLzgdBaseInfos);

            if (_validMsg.length() > 0) {
                return ResultVoUtil.error(_validMsg.toString());
            } else {
                this.baseInfoService.exeImport(newLzgdBaseInfos);
                return ResultVoUtil.success("数据导入成功");
            }

        } catch (ProjectMatchException var13) {
            var13.printStackTrace();
            return ResultVoUtil.error(var13.getMessage());
        } catch (FileNotFoundException var14) {
            var14.printStackTrace();
            return ResultVoUtil.error("数据导入失败");
        }
    }


    private Map<String, Integer> getFieldMap(List<List<String>> rows, int titleRow) {
        Map<String, Integer> fieldMap = new HashMap();
        List<String> fields = (List)rows.get(titleRow);

        for(int i = 0; i < fields.size(); ++i) {
            String field = (String)fields.get(i);
            fieldMap.put(field, i);
        }

        return fieldMap;
    }


    private List<BaseInfo> parseBaseInfos(List<List<String>> rows, Map<String, Integer> fieldMap) {
        List<BaseInfo> gdps = new ArrayList();

        for(int i = RegionGdpServiceImpl.DATA_START_ROW; i < rows.size(); ++i) {
            List<String> cells = (List)rows.get(i);
            BaseInfo gdp = new BaseInfo();
            Field[] fields = gdp.getClass().getDeclaredFields();

            for(int j = 0; j < fields.length; ++j) {
                Field field = fields[j];
                String fieldName = field.getName();
                if (fieldMap.containsKey(fieldName)) {
                    int cIndex = (Integer)fieldMap.get(fieldName);
                    if(fieldName.equals("mj")){

                    }
                    Object value = cells.get(cIndex);
                    //时间格式字段
                    if(fieldName.equals("xfpc")||fieldName.equals("jssj")||fieldName.equals("wczgsj")
                    ||fieldName.equals("czsj")||fieldName.equals("yjwcsj")||fieldName.equals("qrxzMonth")){
                        String _value= getTime(value.toString());
                        if(!StringUtil.isEmpty(_value)){
                            value=_value;
                        }
                    }
                    this.setField(gdp, field, value);
                }
            }

            gdps.add(gdp);
        }

        return gdps;
    }

    private void setField(BaseInfo gdp, Field field, Object fieldValue) {
        try {
            Class clz = gdp.getClass();
            String name = field.getName();
            name = name.substring(0, 1).toUpperCase() + name.substring(1);
            String type = field.getGenericType().toString();
            Method m;
            if (type.equals("class java.lang.String") && fieldValue != null) {
                String value = (String)fieldValue;
                m = clz.getMethod("set" + name, String.class);
                m.invoke(gdp, value);
            }

            if (type.equals("class java.lang.Integer") && fieldValue != null && !StringUtil.isEmpty(fieldValue.toString())) {
                Integer value = Integer.parseInt(fieldValue.toString());
                m = clz.getMethod("set" + name, Integer.class);
                m.invoke(gdp, value);
            }

            if (type.equals("class java.lang.Double") && fieldValue != null && !StringUtil.isEmpty(fieldValue.toString())) {
                Double value = Double.parseDouble(fieldValue.toString());
                m = clz.getMethod("set" + name, Double.class);
                m.invoke(gdp, value);
            }

            if (type.equals("class java.lang.Boolean") && fieldValue != null && !StringUtil.isEmpty(fieldValue.toString())) {
                Boolean value = Boolean.parseBoolean(fieldValue.toString());
                m = clz.getMethod("set" + name, Boolean.class);
                m.invoke(gdp, value);
            }

            if (type.equals("class java.util.Date") && fieldValue != null && !StringUtil.isEmpty(fieldValue.toString())) {
                Date value = DateUtil.fromString(fieldValue.toString());
                m = clz.getMethod("set" + name, Date.class);
                m.invoke(gdp, value);
            }
        } catch (NoSuchMethodException var9) {
            var9.printStackTrace();
        } catch (SecurityException var10) {
            var10.printStackTrace();
        } catch (IllegalAccessException var11) {
            var11.printStackTrace();
        } catch (IllegalArgumentException var12) {
            var12.printStackTrace();
        } catch (InvocationTargetException var13) {
            var13.printStackTrace();
        }

    }

    /**
     * 统计数据
     */
    @GetMapping("/statNewLZCountByCity")
    @ResponseBody
    public ResultVo statNewLZCountByCity() {
        List<Map<String, String>> maps = baseInfoService.statTotalNewLZCount();
        return ResultVoUtil.success(maps);
    }

    /**
     * 按城市级别统计未整改数据
     */
    @GetMapping("/statUnLZCountByCityLevel")
    @ResponseBody
    public ResultVo statUnLZCountByCityLevel(
            @RequestParam(required = false) String cityLevel
    ) {
        List<Map<String, String>> maps = baseInfoService.statUnLZCountByCityLevel(cityLevel);
        return ResultVoUtil.success(maps);
    }



    //Mysql支持的时间戳限制
    static long minTime = Timestamp.valueOf("1970-01-01 09:00:00").getTime();
    static long maxTime = Timestamp.valueOf("2038-01-19 11:00:00").getTime();
    static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日");

    //判断 并转换时间格式 ditNumber = 43607.4166666667
    public static String getTime(String ditNumber) {
        //如果不是数字
        if(!isNumeric(ditNumber)){
            return null;
        }
        //如果是数字 小于0则 返回
        BigDecimal bd = new BigDecimal(ditNumber);
        //如果不符合时间基础
        double longDitNum = new Double(ditNumber);
        if(longDitNum<40000){
            return null;
        }

        int days = bd.intValue();//天数
//        int mills = (int) Math.round(bd.subtract(new BigDecimal(days)).doubleValue() * 24 * 3600);

        //获取时间
        Calendar c = Calendar.getInstance();
        c.set(1900, 0, 1);
        c.add(Calendar.DATE, days - 2);
        try {
            String returnTime=dateFormat.format(c.getTime());
         return returnTime;
        } catch (Exception e) {
            System.out.println("传入日期错误" + c.getTime());
        }
        return null;
    }

    //校验是否数据含小数点
    private static boolean isNumeric(String str){
        Pattern pattern = Pattern.compile("[0-9]+\\.*[0-9]*");
        Matcher isNum = pattern.matcher(str);
        if(!isNum.matches()){
            return false;
        }
        return true;
    }
}